{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/interactive-coding-challenges)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Solution Notebook"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Problem: Find the sum of two integers without using the + or - sign.\n",
    "\n",
    "* [Constraints](#Constraints)\n",
    "* [Test Cases](#Test-Cases)\n",
    "* [Algorithm](#Algorithm)\n",
    "* [Code](#Code)\n",
    "* [Unit Test](#Unit-Test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Constraints\n",
    "\n",
    "* Can we assume the inputs are valid?\n",
    "    * No, check for None\n",
    "* Can we assume this fits memory?\n",
    "    * Yes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test Cases\n",
    "\n",
    "<pre>\n",
    "* None input -> TypeError\n",
    "* 5, 7 -> 12\n",
    "* -5, -7 -> -12\n",
    "* 5, -7 -> -2\n",
    "</pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Algorithm\n",
    "\n",
    "We'll look at the following example, adding a and b:\n",
    "\n",
    "<pre>\n",
    "a 0111 \n",
    "b 0101\n",
    "</pre>\n",
    "\n",
    "First, add a and b, without worrying about the carry (0+0=0, 0+1=1, 1+1=0):\n",
    "\n",
    "result = a ^ b = 0010\n",
    "\n",
    "Next, calculate the carry (1+1=2).  We'll need to left shift one to prepare for the next iteration when we move to the next most significant bit:\n",
    "\n",
    "carry = (a&b) << 1 = 1010\n",
    "\n",
    "If the carry is not zero, we'll need to add the carry to the result.  Recursively call the function, passing in result and carry.\n",
    "\n",
    "Below are the values of a, b, and the carry of a = 7 and b = 5, producing the result of 12.\n",
    "\n",
    "<pre>\n",
    "a 0111 \n",
    "b 0101 \n",
    "----- \n",
    "c 0101 \n",
    "a 0010 \n",
    "b 1010 \n",
    "----- \n",
    "c 0010 \n",
    "a 1000 \n",
    "b 0100 \n",
    "----- \n",
    "c 0000 \n",
    "a 1100 \n",
    "b 0000\n",
    "\n",
    "c = carry = 0, return the result 1100\n",
    "</pre>\n",
    "\n",
    "Complexity:\n",
    "* Time: O(b), where b is the number of bits\n",
    "* Space: O(b), where b is the number of bits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Solution(object):\n",
    "\n",
    "    def sum_two(self, a, b):\n",
    "        if a is None or b is None:\n",
    "            raise TypeError('a or b cannot be None')\n",
    "        result = a ^ b;\n",
    "        carry = (a&b) << 1\n",
    "        if carry != 0:\n",
    "            return self.sum_two(result, carry)\n",
    "        return result;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Unit Test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting test_sum_two.py\n"
     ]
    }
   ],
   "source": [
    "%%writefile test_sum_two.py\n",
    "import unittest\n",
    "\n",
    "\n",
    "class TestSumTwo(unittest.TestCase):\n",
    "\n",
    "    def test_sum_two(self):\n",
    "        solution = Solution()\n",
    "        self.assertRaises(TypeError, solution.sum_two, None)\n",
    "        self.assertEqual(solution.sum_two(5, 7), 12)\n",
    "        self.assertEqual(solution.sum_two(-5, -7), -12)\n",
    "        self.assertEqual(solution.sum_two(5, -7), -2)\n",
    "        print('Success: test_sum_two')\n",
    "\n",
    "\n",
    "def main():\n",
    "    test = TestSumTwo()\n",
    "    test.test_sum_two()\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Success: test_sum_two\n"
     ]
    }
   ],
   "source": [
    "%run -i test_sum_two.py"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
